package cn.maihe.elg.operation.supports.electronicseal.kt.cloudsign.dto;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author caixh
 * @Date 2022/8/10.
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ContractPushReqDTO {

    private String name;//合同签署流程名称	String	0	Y	合同签署流程名称
    private String sortType;//	签章顺序类型	String	0	Y	1无序签章，2顺序签章
    private String fileType;//	签章版式类型	String	0	Y	1PDF，2OFD（暂不支持）
    private String overTime;//超时时间	String	0	Y	-1代表不设超时，单位为分钟
    private List<FileArr> fileArr;//文件对象数组	Object[]	0	Y	文件对象数组（详见下方说明）
    private List<UserArr> userArr;//用户信息	Object	0	Y	用户信息（详见下方说明）


    public static ContractPushReqDTO buildReqDTO(String signFlowName, List<SignFileInfo> signFileInfoList) {
        ContractPushReqDTO reqDTO = new ContractPushReqDTO();
        reqDTO.setName(signFlowName);
        reqDTO.setSortType("1");
        reqDTO.setFileType("1");
        reqDTO.setOverTime("-1");
        reqDTO.setFileArr(buildFileArrList(signFileInfoList));
        reqDTO.setUserArr(buildUserArrList(signFileInfoList));
        return reqDTO;
    }

    /**
     * @param fileId   上传文件接口返回文件id
     * @param fileName 文件名称
     * @return
     */
    public static SignFileInfo buildSignFileInfo(String fileId, String fileName) {
        SignFileInfo signFileInfo = new SignFileInfo();
        signFileInfo.setFileId(fileId);
        signFileInfo.setFileName(fileName);
        return signFileInfo;
    }


    @Data
    public static class FileArr implements Serializable {
        private String fileName;// 文件名称
        private String fileId;// 文件id（调用文件上传接口返回）
        private String remark;// 备注（非必传）
        private List<SignArr> signArr;
    }

    /**
     * 用户数组
     */
    @Data
    public static class UserArr implements Serializable {
        private String user;//”user”: 用户手机号或企业信用代码
        private String type = "1";//用户类型（1企业，2个人）
        private String sort;
        private String name;//姓名或企业名称
        private List<DeviceArr> deviceArr; //设备数组
        private String idCard;//授权人身份证号（设备类型为5时必传，企业用户且签章类型有人脸授权云签时可传）
        private String mobile;//授权人手机号（企业用户且签章类型有短信授权云签时可传）
        private String isModify;//是否可修改授权人手机号或身份证号（1可修改，2不可修改），默认为1，非必传
        private String width;//个人签章宽度，单位mm（非必传，仅限设备类型5）
        private String height;//个人签章高度，单位mm（非必传，仅限设备类型5）
    }

    /**
     * 设备数组
     */
    @Data
    @NoArgsConstructor
    public static class DeviceArr implements Serializable {
        /**
         * 设备类型与签章类型关系说明：
         * 5发送短信：4个人事件云签
         * 6手机H5接口：2短信授权云签，4个人事件云签
         * 8或者9 pc接口：2短信授权云签，5key介质签
         */
        private String deviceType;// 设备类型（5发送短信，6手机H5接口，8pc接口）
        private List<String> signTypeArr;// 签章类型数组：2短信授权云签，4个人事件云	签，5key介质签

        public DeviceArr(String deviceType, List<String> signTypeArr) {
            this.deviceType = deviceType;
            this.signTypeArr = signTypeArr;
        }
    }

    @Data
    public static class SignArr implements Serializable {
        private String user;// 用户手机号或企业信用代码
        private String mode;// 模式（1移动盖章，2固定位置盖章，3关键字盖章）
        private Map<String, String> modeVal;//  { 模式值，mode为3时必传key: 关键字
    }


    @Data
    public static class SignFileInfo implements Serializable {
        private String fileId; //文件id（调用文件上传接口返回）
        private String fileName;//文件名称
        //同个文件支持多个签章
        private List<SignInfoVO> signInfoVOS;

        public SignFileInfo addSignInfo(String user, String name, String signKeyVal, String authMobile, String type) {
            SignInfoVO vo = new SignInfoVO(user, name, signKeyVal, authMobile, type);
            if (signInfoVOS == null) {
                this.signInfoVOS = Lists.newArrayList(vo);
            } else {
                signInfoVOS.add(vo);
            }
            return this;
        }

        public SignFileInfo addSignInfo(String user, String name, String signKeyVal, int offsetX, int offsetY, String authMobile, String type) {
            SignInfoVO vo = new SignInfoVO(user, name, signKeyVal, offsetX, offsetY, authMobile, type);
            if (signInfoVOS == null) {
                this.signInfoVOS = Lists.newArrayList(vo);
            } else {
                signInfoVOS.add(vo);
            }
            return this;
        }
    }

    @Data
    @NoArgsConstructor
    public static class SignInfoVO implements Serializable {
        public SignInfoVO(String user, String name, String signKeyVal, String authMobile, String type) {
            this.user = user;
            this.name = name;
            this.signKeyVal = signKeyVal;
            this.authMobile = authMobile;
            this.type = type;
        }

        public SignInfoVO(String user, String name, String signKeyVal, int offsetX, int offsetY, String authMobile, String type) {
            this.user = user;
            this.name = name;
            this.signKeyVal = signKeyVal;
            this.offsetX = offsetX;
            this.offsetY = offsetY;
            this.authMobile = authMobile;
            this.type = type;
        }

        private String user;//用户手机号或企业信用代码
        private String name;//姓名或企业名称
        private String signKeyVal;//固定为关键字签章 关键字签章 目前为企业名称前20字符
        private int offsetX;//根据关键字x位置偏移量，单位mm（mode为3时选传）
        private int offsetY;//根据关键字y位置偏移量，单位mm（mode为3时选传）
        private String authMobile;//：授权人手机号（企业用户且签章类型有短信授权云签时可传）

        private String type; // 用户类型（1企业，2个人）
    }

    /**
     * 签署数据之签署文件信息
     */
    private static List<FileArr> buildFileArrList(List<SignFileInfo> signFileInfoList) {
        List<FileArr> fileArrList = signFileInfoList.stream().map(signFileInfo -> {

            FileArr fileArr = new FileArr();
            fileArr.setFileName(signFileInfo.getFileName());
            fileArr.setFileId(signFileInfo.getFileId());

            List<SignArr> signArrList = signFileInfo.signInfoVOS.stream().map(vo -> {
                SignArr signArr = new SignArr();
                signArr.setUser(vo.getUser());
                signArr.setMode("3");
                signArr.setModeVal(new HashMap<String, String>() {{
                    put("key", vo.getSignKeyVal());
                    put("offsetX", String.valueOf(vo.getOffsetX()));
                    put("offsetY", String.valueOf(vo.getOffsetY()));
                }});
                return signArr;
            }).collect(Collectors.toList());

            fileArr.setSignArr(signArrList);

            return fileArr;
        }).collect(Collectors.toList());
        return fileArrList;
    }


    private static List<UserArr> buildUserArrList(List<SignFileInfo> signFileInfoList) {
        List<UserArr> UserArrList = new ArrayList<>();
        Set<String> userSet = Sets.newHashSet();
        signFileInfoList.stream().forEach(fileInfo -> {
            fileInfo.signInfoVOS.stream().filter(signInfo -> !userSet.contains(signInfo.getUser())).
                    forEach(signInfo -> {
                        if (!userSet.contains(signInfo.getUser())) {
                            UserArr userArr = new UserArr();
                            userArr.setUser(signInfo.getUser());
                            userArr.setType(signInfo.getType());
                            userArr.setName(signInfo.getName());
                            userArr.setMobile(signInfo.getAuthMobile());
                            List<DeviceArr> deviceArrList = Lists.newArrayList(
                                    new DeviceArr("8", Lists.newArrayList("2")),
                                    new DeviceArr("9", Lists.newArrayList("2")
                                    ));
                            userArr.setDeviceArr(deviceArrList);
                            userSet.add(signInfo.getUser());
                            UserArrList.add(userArr);
                        }
                    });
        });
        return UserArrList;
    }

}
